#include "RtJob.h"

RtJob::RtJob(const QString& name) :
    RtObject(name), armed_(false), slave_(false)
{
}
RtJob::~RtJob(void)
{
}
void RtJob::detach()
{
    setArmed(false);
    RtObject::detach();
}
bool RtJob::throwIfArmed()
{
	if (armed_) throwScriptError("Not possible when armed");
	return armed_;
}
void RtJob::exec()
{
	//** Job has been locked at the RtLoop level
	if (armed_)
	{
        // run this job's task
		run();
		// execute all child tasks
        subjobs_.exec();
	}
}
bool RtJob::setArmed(bool on)
{
    if (on == armed_) return armed_;

    if (armed_) // disarm
    {
        jobLock();
        disarm_();
        foreach(RtJob* j, subjobs_) if (j->slave()) j->setArmed(false);
        armed_ = false;
        jobUnlock();
    }
    else // arm
    {
        // select my subjobs
        subjobs_.clear();
        foreach(RtObject* obj, children_)
        {
            RtJob* job = qobject_cast<RtJob*>(obj);
            if (job) subjobs_ << job;
        }

        // lock & arm (only my slave-jobs)
        jobLock();
        bool ok = arm_();
        JobList::iterator i = subjobs_.begin();
        while(ok && i!=subjobs_.end()) {
            if ((*i)->slave()) ok = (*i)->setArmed(true);
            ++i;
        }

        // Some job failed to arm.
        // the job that failed must send an error
        if (!ok)
        {

            disarm_();
            foreach(RtJob* j, subjobs_) if (j->slave()) j->setArmed(false);
            armed_ = false;
        }

        jobUnlock();

    }
	emit propertiesChanged();
	return armed_;
}
bool RtJob::setSlave(bool on)
{
    if (on == slave_) return slave_;
    auto_lock L(comm_lock);
    slave_ = on;
    emit propertiesChanged();
    return slave_;
}

//////////////////// RtLoop //////////////////////////////////////////
RtLoop::RtLoop(const QString& name) :
    RtJob(name)
{
}
RtLoop::~RtLoop(void)
{
}
void RtLoop::exec()
{
    // Lock this Loop & subjobs
    jobLock();
    // call base-class exec
    RtJob::exec();
    // unlock everything in reverse order
    jobUnlock();
}

/////////////////////// RtDelayLoop /////////////////////////////
RtDelayLoop::RtDelayLoop(const QString& name) :
RtLoop(name), delay_(1), counter_(1)
{
}
RtDelayLoop::~RtDelayLoop(void)
{
}
void RtDelayLoop::exec()
{
    comm_lock.lock();
    if (counter_) counter_--;
    if (counter_ == 0)
    {
        counter_ = delay_;
        RtLoop::exec();
    }
    comm_lock.unlock();
}
void RtDelayLoop::setDelay(unsigned int d)
{
    if (delay_ != d)
    {
        // locked code
        {
            auto_lock L(comm_lock);
            delay_ = d;
            counter_ = delay_;
        }
        emit propertiesChanged();
    }
}

